/*
 * Copyright Red Hat, Inc. and/or its affiliates
 * and other contributors as indicated by the @author tags and
 * the COPYRIGHT.txt file distributed with this work.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.teiid;

import java.io.Serializable;
import java.sql.Statement;
import java.util.Map;
import java.util.TimeZone;

import javax.security.auth.Subject;

import org.teiid.adminapi.DataPolicy;
import org.teiid.adminapi.Session;
import org.teiid.adminapi.VDB;
import org.teiid.jdbc.TeiidConnection;
import org.teiid.jdbc.TeiidSQLException;
import org.teiid.jdbc.TeiidSQLWarning;

/**
 * Context information for the currently executing command.
 * Can be used as an argument to UDFs.
 */
public interface CommandContext {

    /**
     * Get the current user name, which will just be the base user name
     * and not include the security domain.  See also {@link #getSession()} - {@link Session#getSecurityDomain()}
     * @return
     */
    String getUserName();

    /**
     * Get the current vdb name
     * @return
     */
    String getVdbName();

    /**
     * Get the current vdb version
     * @return
     */
    String getVdbVersion();

    /**
     * Get the connection id
     * @return
     */
    String getConnectionId();

    /**
     * Get the connection id
     * @return
     * @deprecated see {@link #getConnectionId()}
     */
    @Deprecated
    String getConnectionID();

    /**
     * Get the next random double value
     * @return
     */
    double getNextRand();

    /**
     * Sets the seed value and returns the next random double value.
     * Additional calls to {@link #getNextRand()} will be based upon the seed value.
     * @param seed
     * @return
     */
    double getNextRand(long seed);

    /**
     * Get the processor batch size set on the BufferManager
     * @return - the nominal batch size target.  actual batch sizes will vary based
     * upon the column types
     */
    int getProcessorBatchSize();

    /**
     * Get the server {@link TimeZone}
     * @return
     */
    TimeZone getServerTimeZone();

    /**
     * Get the current subject
     * @return
     */
    Subject getSubject();

    /**
     * Get the current session
     * @return
     */
    Session getSession();

    /**
     * Get the current command payload
     * @return may be null if the client did not set a payload
     */
    Serializable getCommandPayload();

    /**
     * Get the current request id
     * @return
     */
    String getRequestId();

    /**
     * Get the user's data policies, never null
     * @return
     */
    Map<String, DataPolicy> getAllowedDataPolicies();

    /**
     * Get the current vdb
     * @return
     */
    VDB getVdb();

    /**
     * Add a listener for command events
     * @param listener
     */
    void addListener(CommandListener listener);

    /**
     * Add a listener for command events
     * @param listener
     */
    void removeListener(CommandListener listener);

    /**
     * Get the number of times this command has been reused.  Useful
     * in continuous executions.
     * @see #isContinuous()
     * @return
     */
    long getReuseCount();

    /**
     * Get class loader for VDB.
     * @return
     */
    ClassLoader getVDBClassLoader();

    /**
     * Add an exception as a warning.  The exception will be wrapped by a {@link TeiidSQLWarning} for the client.
     * The warnings can be consumed through the {@link Statement#getWarnings()} method.
     * @param ex
     */
    void addWarning(Exception ex);

    /**
     *
     * @return true if this is a continuous query
     */
    boolean isContinuous();

    /**
     * Whether to return the keys generated by an insert.
     * @return true
     */
     @Deprecated
    boolean isReturnAutoGeneratedKeys();

    /**
     * Creates a holder for generated keys.
     * @param columnNames
     * @param columnDataTypes
     * @return
     */
    GeneratedKeys returnGeneratedKeys(String[] columnNames,
            Class<?>[] columnDataTypes);

    /**
     * Returns the last set of generated keys for the current command or null if no keys have been generated.
     */
    GeneratedKeys getGeneratedKeys();

    /**
     * Set the session variable and return the old value if any
     * @param key
     * @param value
     * @return
     */
    Object setSessionVariable(String key, Object value);

    /**
     * Get the session variable
     * @param key
     * @return
     */
    Object getSessionVariable(String key);

    /**
     * Gets a connection to the current session.
     * <br><b>WARNING</b> be careful with blocking/recursive operations.
     * <br>The returned connection is considered to be derived and is not allowed
     * to alter the transaction state or close the session.
     * <br>Each call to this method will return a new connection.
     * <br>Client side execution/connection properties are specific to
     * each connection instance
     * @return a Connection to the current session
     * @throws TeiidSQLException
     */
    TeiidConnection getConnection() throws TeiidSQLException;
}
